#coding=utf-8
#
# Copyright (C) 2014  NianNian TECH Co., Ltd. All rights reserved.
# Created on Sep 17, 2014, by Junn
#
from regards.models import Regard, NewRegardMessage, DateTip
from utils import logs
from celery import task
from django.db.models.aggregates import Count
import settings
from django.utils import timezone
from django.db.models.expressions import F


@task
def query_waiting_regards():
    '''定时查询DB, 检查是否有待发送的问候, 有则组装成以下结构并存入NewRegardMessage队列.
    
    waitlist为QuerySet, 推送成功后用于更新对应的Regard数据状态(status='S')
    
    regard_messages为ValuesQuerySet对象类型, 结构如下: 
        {'count': 2, 'receiver': 1L, 'author': 1L}
        {'count': 1, 'receiver': 10000001L, 'author': 1L}
        {'count': 1, 'receiver': 10000002L, 'author': 1L}
        {'count': 6, 'receiver': 10000002L, 'author': 10000001L}
        {'count': 1, 'receiver': 10000003L, 'author': 1L}
        {'count': 1, 'receiver': 10000003L, 'author': 10000001L}
    '''
    
    waitlist = Regard.objects.get_send_waitlist()
    if not waitlist:
        logs.debug('No regards waiting sent ')
        return
    
    # 分组并统计同一个问候接收者的问候数量
    regard_messages = waitlist.values('author', 'receiver').annotate(count=Count('receiver'))
    
    #TODO: loop access DB here...
    for rm in regard_messages:  
        try:
            msg, created = NewRegardMessage.objects.get_or_create(
                sender=rm['author'], receiver=rm['receiver']
            )
            latest_regard = waitlist.filter(author=rm['author'], receiver=rm['receiver']).order_by('-sent_time')[0]
            msg.set_extra_info(rm['count'], 'R', u'[问候]', latest_regard.sent_time)
        except Exception, e:
            logs.warn(e)
            pass    
    
    waitlist.update(status='S') 
    #s_regard_waitlist_push.send(sender=Regard, waitlist=waitlist)
    
# 系统预设的提醒发送者id    
SYS_TIP_SENDER = settings.SYS_TIP_SENDER
    
@task
def query_waiting_datetips():
    '''查询触发的事件提醒, 存入到消息队列. FUTURE: 后期可考虑多级队列, 以提升性能
    与query_waiting_regards有重复代码, 后续重构
    '''
    waitlist = DateTip.objects.get_datetip_waitlist()
    if not waitlist:
        logs.debug('No datetips waiting triggered ')
        return    
    
    # 分组并统计同一个提醒拥有者的新提醒数量
    tip_messages = waitlist.values('creator').annotate(count=Count('creator'))
    
    #TODO: loop access DB here...
    for m in tip_messages:  
        try:
            msg, created = NewRegardMessage.objects.get_or_create(
                sender=SYS_TIP_SENDER, receiver=m['creator']
            )
            latest_tip = waitlist.filter(creator=m['creator']).order_by('-spec_date')[0]
            msg.set_extra_info(m['count'], 'T', latest_tip.title, latest_tip.spec_date)
        except Exception, e:
            logs.warn(e)
            pass    
    
    waitlist.update(is_triggered=True)

@task        
def push_new_messages():
    '''定时扫描问候消息表, 将未发送的问候消息推送到远端消息服务器(如jpush)
    
    推送条件:
        count>0 and is_pushed=False and pushed_err_count<5
    '''
    
    messages = NewRegardMessage.objects.filter(
        count__gt=0, is_pushed=False, pushed_err_count__lt=5
    ) 
    if not messages:
        return
    
    logs.debug('Start pushing...')
    for msg in messages:
        msg.push()
            
    logs.debug('Push ended.')

@task
def clear_pushed_err_count():
    '''每隔一定小时将未成功推送的错误消息计数(pushed_err_count)清0'''
    NewRegardMessage.objects.filter(count__gt=0, is_pushed=False, 
                                    pushed_err_count__gt=0).update(pushed_err_count=0)
                                    
@task
def incr_datetip_year():
    '''提醒若已过期(且已读), 则将年份加1, 以便下一年再次提醒. 每天执行一次'''
    now = timezone.now()
    DateTip.objects.filter(is_triggered=True, is_checked=True, spec_date__lt=now).update(
        spec_date=F('spec_date')+timezone.timedelta(365),
        is_triggered=False, 
        is_checked=False,
    )                                    
            
            
# @receiver(s_regard_waitlist_push)
# def push_waitlist_regard(sender, **kwargs):     #TODO: 如果该函数1分钟内处理不完waitlist所有问候推送, 将发生什么情况?
#     '''推送多个问候消息到不同的接收者.
#     '''
#     push_new_messages()
# 
#     #设置各问候状态为"已发送"
#     waitlist = kwargs.pop('waitlist')  #queryset, need to update this set to DB  
#     if not waitlist:
#         return
#     if isinstance(waitlist, Regard):  #Regard object
#         waitlist.status = 'S'
#         waitlist.save()
#     else: #QuerySet
#         waitlist.update(status='S')            
    
# class RegardSendingThread(threading.Thread):
#     def __init__(self, *args, **kwargs):
#         self.started = True
#         threading.Thread.__init__(self, *args, **kwargs)
# 
#     def run(self):
#         logs.info('RegardSendingThread started .')
#         while self.started:
#             send_timed_regards()
#             time.sleep(60)
#             
#     def stop(self):
#         self.started = False  
# 
#     def is_started(self):
#         return self.started
    
